#ifndef PCINTERRUPT_H
#define PCINTERRUPT_H

#include <inttypes.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include "Arduino.h"

typedef void (*PCIntvoidFuncPtr)(void);

//! \cond skip
class PCintPin {
public:
    PCintPin();
    PCIntvoidFuncPtr PCintFunc;
    uint8_t mode;
    uint8_t _pinMask;
    PCintPin* next;
};

class PortInfo {
public:
    volatile uint8_t   *_portRegister;
    uint8_t _prevPortValue;
};
//! \endcond

#define MAX_PORT_INDEX 4

//! Attach handler to any valid PCINT pin
/*!
Attach handler to any valid PCINT pin.  See pins_arduino.h for valid interrupt pins for your hardware\n
Create PCInterrupt myInt; \n
Call myInt.attachInterrupt(uint8_t pin, uint8_t mode, voidFuncPtr userFunc);\n
pin is any valid interrupt pin (HW or PCINT)\n
mode is CHANGE, RISING, FALLING\n
userFunc is the routine you want called  e.g. &recvFunc();  \n
\version 1.3
*/
class PCInterrupt
{
private:
    int addPin(uint8_t pin, uint8_t mode, PCIntvoidFuncPtr userFunc);

public:
    int attachInterrupt(uint8_t pin, uint8_t mode, PCIntvoidFuncPtr userFunc);
    PCInterrupt();
    PortInfo portInfo[MAX_PORT_INDEX];
    inline void dispatchInterrupt(int); // public only for easy access by interrupt handlers

    static inline void dispatchPCINT0(); // public only for easy access by interrupt handlers
    static inline void dispatchPCINT1(); // public only for easy access by interrupt handlers
    static inline void dispatchPCINT2(); // public only for easy access by interrupt handlers
    static inline void dispatchPCINT3(); // public only for easy access by interrupt handlers
protected:
    PCintPin* pinHead;
};

#endif // PCINTERRUPT_H
